
#include "apdu_lib_cryption_mgr.h"
#include "apdu_lib_common.h"
#include "apdu_lib_dev_config.h"

#include "../apdu.core/apdu.h"

#include "../../mk_lib/mk_auto_ptr.h"
#include "../../mk_lib/mk_utility.h"

#include <stdlib.h>
#include <string.h>
#include "../apdu.algo/mac.h"

extern int	g_sw;

int app_encrypt_init( HANDLE devHandle, int app_id, int container_id, unsigned long key_id, 
					 unsigned char * iv, int iv_len, unsigned long padding_type, unsigned long feed_bit_len )
{
	apdu * newApdu  =  NULL;
	newApdu = get_cryption_mgr()->create_apdu_encrypt_init(app_id, container_id, key_id, 
						iv, iv_len, padding_type, feed_bit_len);

	mk_auto_ptr<apdu> ap(newApdu);

	if( 0 != get_dev_mgr()->transmit_apdu(devHandle,newApdu, &g_sw))
	{
		return 1;
	}

	if(g_sw != 0x9000)
	{
		return 2;
	}

	return 0;
}

int app_encrypt( HANDLE devHandle, int app_id, int container_id, unsigned long key_id, 
				unsigned char * input, int input_len, unsigned char * output, int *output_len )
{
	apdu * newApdu  =  NULL;
	newApdu = get_cryption_mgr()->create_apdu_encrypt(app_id, container_id, key_id, input, input_len);

	mk_auto_ptr<apdu> ap(newApdu);

	if( 0 != get_dev_mgr()->transmit_apdu(devHandle,newApdu, &g_sw))
	{
		return 1;
	}

	if(g_sw != 0x9000)
	{
		return 2;
	}

	int data_len = 0;
	unsigned char * data = newApdu->get_response_data(&data_len);
	if(*output_len < data_len)
	{
		return 3;
	}
	*output_len = data_len;
	memcpy(output, data, data_len);
	return 0;
}

int app_encrypt_update( HANDLE devHandle, int app_id, int container_id, unsigned long key_id,
					   unsigned char * input, int input_len, unsigned char * output, int * output_len )
{
	apdu * newApdu  =  NULL;
	newApdu = get_cryption_mgr()->create_apdu_encrypt_update(app_id, container_id, key_id, input, input_len);

	mk_auto_ptr<apdu> ap(newApdu);

	if( 0 != get_dev_mgr()->transmit_apdu(devHandle,newApdu, &g_sw))
	{
		return 1;
	}

	if(g_sw != 0x9000)
	{
		return 2;
	}

	int data_len = 0;
	unsigned char * data = newApdu->get_response_data(&data_len);

	if(*output_len < data_len)
	{
		return 3;
	}
	*output_len = data_len;

	memcpy(output, data, data_len);
	return 0;
}

int app_encrypt_final( HANDLE devHandle, int app_id, int container_id, unsigned long key_id, 
					  unsigned char * input, int input_len, unsigned char * output, int * output_len )
{
	apdu * newApdu  =  NULL;
	newApdu = get_cryption_mgr()->create_apdu_encrypt_final(app_id, container_id, key_id, input, input_len);

	mk_auto_ptr<apdu> ap(newApdu);

	if( 0 != get_dev_mgr()->transmit_apdu(devHandle,newApdu, &g_sw))
	{
		return 1;
	}

	if(g_sw != 0x9000)
	{
		return 2;
	}

	int data_len = 0;
	unsigned char * data = newApdu->get_response_data(&data_len);
	if(*output_len < data_len)
	{
		return 3;
	}
	*output_len = data_len;
	memcpy(output, data, data_len);
	return 0;
}


int app_decrypt_init( HANDLE devHandle, int app_id, int container_id, unsigned long key_id,
					 unsigned char * iv, int iv_len, unsigned long padding_type, unsigned long feed_bit_len )
{
	apdu * newApdu  =  NULL;
	newApdu = get_cryption_mgr()->create_apdu_decrypt_init(app_id, container_id, key_id,  
		iv, iv_len, padding_type, feed_bit_len);

	mk_auto_ptr<apdu> ap(newApdu);

	if( 0 != get_dev_mgr()->transmit_apdu(devHandle,newApdu, &g_sw))
	{
		return 1;
	}

	if(g_sw != 0x9000)
	{
		return 2;
	}

	return 0;
}

int app_decrypt( HANDLE devHandle, int app_id, int container_id, unsigned long key_id, 
				unsigned char * input, int input_len, unsigned char * output, int * output_len )
{
	apdu * newApdu  =  NULL;
	newApdu = get_cryption_mgr()->create_apdu_decrypt(app_id, container_id, key_id, input, input_len);

	mk_auto_ptr<apdu> ap(newApdu);

	if( 0 != get_dev_mgr()->transmit_apdu(devHandle,newApdu, &g_sw))
	{
		return 1;
	}

	if(g_sw != 0x9000)
	{
		return 2;
	}

	int data_len = 0;
	unsigned char * data = newApdu->get_response_data(&data_len);
	if(*output_len < data_len)
	{
		return 3;
	}
	*output_len = data_len;
	memcpy(output, data, data_len);
	return 0;
}

int app_decrypt_update( HANDLE devHandle, int app_id, int container_id, unsigned long key_id,
					   unsigned char * input, int input_len, unsigned char * output, int * output_len )
{
	apdu * newApdu  =  NULL;
	newApdu = get_cryption_mgr()->create_apdu_decrypt_update(app_id, container_id, key_id, input, input_len);

	mk_auto_ptr<apdu> ap(newApdu);

	if( 0 != get_dev_mgr()->transmit_apdu(devHandle,newApdu, &g_sw))
	{
		return 1;
	}

	if(g_sw != 0x9000)
	{
		return 2;
	}

	int data_len = 0;
	unsigned char * data = newApdu->get_response_data(&data_len);
	if(*output_len < data_len)
	{
		return 3;
	}
	*output_len = data_len;

	memcpy(output, data, data_len);
	return 0;
}

int app_decrypt_final( HANDLE devHandle, int app_id, int container_id, unsigned long key_id, 
					  unsigned char * input, int input_len, unsigned char * output, int * output_len )
{
	apdu * newApdu  =  NULL;
	newApdu = get_cryption_mgr()->create_apdu_decrypt_final(app_id, container_id, key_id, input, input_len);

	mk_auto_ptr<apdu> ap(newApdu);

	if( 0 != get_dev_mgr()->transmit_apdu(devHandle,newApdu, &g_sw))
	{
		return 1;
	}

	if(g_sw != 0x9000)
	{
		return 2;
	}

	int data_len = 0;
	unsigned char * data = newApdu->get_response_data(&data_len);
	if(*output_len < data_len)
	{
		return 3;
	}
	*output_len = data_len;

	memcpy(output, data, data_len);
	return 0;
}


int app_encrypt_update_hs(HANDLE devHandle, unsigned long algo_id,
						  int appid, int containerId, int keyId,
						  int firstPackage, unsigned char * iv, int iv_len,
						  unsigned char * input, int input_len, unsigned char * output, int *output_len)
{
	return app_dev_crypt_with_high_speed(devHandle, algo_id, 1, 
					appid, containerId, keyId, firstPackage, iv, iv_len, 
					input, input_len, output, output_len);
}

int app_decrypt_update_hs(HANDLE devHandle, int algo_id, 
						  int appid, int containerId, int keyId,
						  int firstPackage, unsigned char * iv, int iv_len,
						  unsigned char * input, int input_len, unsigned char * output, int *output_len)
{
	return app_dev_crypt_with_high_speed(devHandle, algo_id, 0, 
			appid, containerId, keyId, firstPackage, iv, iv_len, 
			input, input_len, output, output_len);
}

